/*
    Copyright (C) 2010-2011 mdis
    
    This file is part of mdis.
    Written by Ketfi-Chérif Mehdi <ketficherif.mehdi@gmail.com>
    	   and Laügt Franz <znarf94@gmail.com>

    mdis is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    mdis is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with mdis.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "plugins-global.h"
#include "8x51.h"

plugin_desc_t desc = {
	device ,
	(char **)register_name ,
	NREGISTERS ,
};

uint8_t 
 init ( uint8_t * rom , uint16_t nbytes )
{
	uint16_t i;
	uint16_t addr, nbytes_copied = 0;
	uint8_t * codeptr = rom;
	uint8_t j, nbytes_line;

	memset ( mcu.data , 0x00 , sizeof (mcu.data) );
	/* for(i=0;i<256;i++)
	{
		mcu.data[i] = 0;
	} */

	memset ( mcu.xdata , 0x00 , sizeof (mcu.xdata) );
	memset ( mcu.code , 0x00 , sizeof (mcu.code) );
	/*for(i=0;i<32768;i++)
	{
		mcu.xdata[i] = 0;
		mcu.code[i] = 0;
	}*/

	while(nbytes_copied < nbytes)
	{
		nbytes_line = *codeptr;
		addr = (*(codeptr+1)<<8) + *(codeptr+2);
		codeptr+=3;
	
		for(j=0;j<nbytes_line;j++)
		{
			mcu.code[addr+j] = *codeptr;
			codeptr++;
			nbytes_copied++;
		}
	}

	//put here the reset values of SFRs and SBITs
	SP = 0x07;
	P0 = 0xFF;
	P1 = 0xFF;
	P2 = 0xFF;
	P3 = 0xFF;
	P4 = 0xFF;

	i = 0;
	while(mcu.code[i] == 0x00)
		i++;
	mcu.start_addr = i;
	mcu.pc = 0;

	return 0;
}

uint8_t 
 get_register ( uint8_t reg )
{
	return mcu.data[registers_mmap[reg]];
}

instruction_t *
 disasm ( uint8_t * rom , uint16_t offset )
{
	uint16_t i;
	for ( i = 0; i < NINSTRUCTIONS ; i++ )
	{
		if ( rom[offset] == inst[i].opcode )
			return &inst[i];
	}
	return NULL;
}

/*
char *
 regs_mmap ( uint8_t addr )
{
	uint16_t i;
	for ( i = 0; i < NREGISTERS ; i++ )
	{
		if ( addr == registers_mmap[i] )
			return &registers_mmap[i];
	}
	return NULL;
}
*/

uint8_t *
 get_memory_code ( void )
{ return &mcu.code[0]; }

uint8_t *
 get_internal_ram ( void )
{ return &mcu.data[0]; }

uint8_t *
 get_external_ram ( void )
{ return &mcu.xdata[0]; }

uint16_t *
 get_pc ( void )
{ return &mcu.pc; }

simul_t *
 simul ( void )
{
	uint8_t tmp, ncycles;
	uint16_t tmp16, i;

	uint16_t addr = mcu.pc;

	switch(mcu.code[addr])
	{
		case 0x00:	//nop
			mcu.pc++;
			break;
		case 0x01:	//ajmp mcu.pc11
			mcu.pc+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0x02:	//ljmp mcu.pc16
			mcu.pc = (mcu.code[addr+1]<<8) + mcu.code[addr+2];
			break;
		case 0x03:	//rr A
			ACC = (ACC>>1) + ((ACC & 0x01)<<7);
			mcu.pc++;
			break;
		case 0x04:	//inc A
			ACC++;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x05:	//inc direct
			mcu.data[mcu.code[addr+1]]++;
			mcu.pc+=2;
			break;
		case 0x06:	//inc @R0
			mcu.data[R0]++;
			mcu.pc++;
			break;
		case 0x07:	//inc @R1
			mcu.data[R1]++;
			mcu.pc++;
			break;
		case 0x08:	//inc R0
			R0++;
			mcu.pc++;
			break;
		case 0x09:	//inc R1
			R1++;
			mcu.pc++;
			break;
		case 0x0A:	//inc R2
			R2++;
			mcu.pc++;
			break;
		case 0x0B:	//inc R3
			R3++;
			mcu.pc++;
			break;
		case 0x0C:	//inc R4
			R4++;
			mcu.pc++;
			break;
		case 0x0D:	//inc R5
			R5++;
			mcu.pc++;
			break;
		case 0x0E:	//inc R6
			R6++;
			mcu.pc++;
			break;
		case 0x0F:	//inc R7
			R7++;
			mcu.pc++;
			break;
		case 0x10:	//jbc bit,rel
			mcu.pc+=3;
			if(GETBIT(mcu.code[addr+1]) == 1)
			{
				CLRBIT(mcu.code[addr+1]);
				mcu.pc += (signed char)mcu.code[addr+2];
			}
			break;
		case 0x11:	//acall mcu.pc11
			mcu.pc+=2;
			mcu.data[SP+1] = mcu.pc & 0xFF;
			mcu.data[SP+2] = mcu.pc >> 8;
			SP+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0x12:	//lcall mcu.pc16
			mcu.pc+=3;
			mcu.data[SP+1] = (uint8_t)mcu.pc%256;
			mcu.data[SP+2] = (uint8_t)mcu.pc>>8;
			SP+=2;
			mcu.pc = (mcu.code[addr+1]<<8)+mcu.code[addr+2];
			break;
		case 0x13:	//rrc A
			tmp = ACC & 0x01;
			ACC = (ACC>>1) + (PSW & 0x01);
			PSW = (tmp == 0x01) ? PSW | 0x80 : PSW & 0x7F;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x14:	//dec A
			ACC--;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x15:	//dec direct
			mcu.data[mcu.code[addr+1]]--;
			mcu.pc+=2;
			break;
		case 0x16:	//dec @R0
			mcu.data[R0]--;
			mcu.pc++;
			break;
		case 0x17:	//dec @R1
			mcu.data[R1]--;
			mcu.pc++;
			break;
		case 0x18:	//dec R0
			R0--;
			mcu.pc++;
			break;
		case 0x19:	//dec R1
			R1--;
			mcu.pc++;
			break;
		case 0x1A:	//dec R2
			R2--;
			mcu.pc++;
			break;
		case 0x1B:	//dec R3
			R3--;
			mcu.pc++;
			break;
		case 0x1C:	//dec R4
			R4--;
			mcu.pc++;
			break;
		case 0x1D:	//dec R5
			R5--;
			mcu.pc++;
			break;
		case 0x1E:	//dec R6
			R6--;
			mcu.pc++;
			break;
		case 0x1F:	//dec R7
			R7--;
			mcu.pc++;
			break;
		case 0x20:	//jb bit,rel
			mcu.pc+=3;
			if(GETBIT(mcu.code[addr+1]) == 1)
			{
				mcu.pc += (signed char)mcu.code[addr+2];
			}
			break;
		case 0x21:	//ajmp mcu.pc11
			mcu.pc+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0x22:	//ret
			SP-=2;
			mcu.pc = (mcu.data[SP+1]<<8) + mcu.data[SP+2];
			break;
		case 0x23:	//rl A
			ACC = (ACC<<1) + ((ACC & 0x80)>>7);
			mcu.pc++;
			break;
		case 0x24:	//add A,#data
			((uint16_t)(ACC + mcu.code[addr+1]) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (mcu.code[addr+1] & 0x0F)) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (mcu.code[addr+1] & 0x7F)) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (mcu.code[addr+1] & 0x7F)) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += mcu.code[addr+1];
			CHECKPARITY();
			mcu.pc+=2;
			break;
		case 0x25:	//add A,direct
			((uint16_t)(ACC + mcu.data[mcu.code[addr+1]]) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (mcu.data[mcu.code[addr+1]] & 0x0F)) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (mcu.data[mcu.code[addr+1]] & 0x7F)) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (mcu.data[mcu.code[addr+1]] & 0x7F)) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0x26:	//add A,@R0
			((uint16_t)(ACC + mcu.data[R0]) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (mcu.data[R0] & 0x0F)) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (mcu.data[R0] & 0x7F)) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (mcu.data[R0] & 0x7F)) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += mcu.data[R0];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x27:	//add A,@R1
			((uint16_t)(ACC + mcu.data[R1]) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (mcu.data[R1] & 0x0F)) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (mcu.data[R1] & 0x7F)) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (mcu.data[R1] & 0x7F)) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += mcu.data[R1];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x28:	//add A,R0
			((uint16_t)(ACC + R0) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R0 & 0x0F)) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R0 & 0x7F)) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R0 & 0x7F)) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += R0;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x29:	//add A,R1
			((uint16_t)(ACC + R1) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R1 & 0x0F)) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R1 & 0x7F)) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R1 & 0x7F)) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += R1;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x2A:	//add A,R2
			((uint16_t)(ACC + R2) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R2 & 0x0F)) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R2 & 0x7F)) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R2 & 0x7F)) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += R2;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x2B:	//add A,R3
			((uint16_t)(ACC + R3) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R3 & 0x0F)) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R3 & 0x7F)) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R3 & 0x7F)) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += R3;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x2C:	//add A,R4
			((uint16_t)(ACC + R4) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R4 & 0x0F)) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R4 & 0x7F)) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R4 & 0x7F)) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += R4;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x2D:	//add A,R5
			((uint16_t)(ACC + R5) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R5 & 0x0F)) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R5 & 0x7F)) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R5 & 0x7F)) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += R5;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x2E:	//add A,R6
			((uint16_t)(ACC + R6) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R6 & 0x0F)) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R6 & 0x7F)) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R6 & 0x7F)) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += R6;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x2F:	//add A,R7
			((uint16_t)(ACC + R7) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R7 & 0x0F)) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R7 & 0x7F)) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R7 & 0x7F)) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += R7;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x30:	//jnb bit,rel
			mcu.pc+=3;
			if(GETBIT(mcu.code[addr+1]) == 0)
			{
				mcu.pc += (signed char)mcu.code[addr+2];
			}
			break;
		case 0x31:	//acall mcu.pc11
			mcu.pc+=2;
			mcu.data[SP+1] = mcu.pc & 0xFF;
			mcu.data[SP+2] = mcu.pc >> 8;
			SP+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0x32:	//reti
			SP-=2;
			mcu.pc = (mcu.data[SP+1]<<8) + mcu.data[SP+2];
			break;
		case 0x33:	//rlc A
			tmp = (ACC & 0x80)>>7;
			ACC = (ACC<<1) + GETBIT(CY);
			if(tmp == 1)
			{
				SETBIT(CY);
			} else {
				CLRBIT(CY);
			}
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x34:	//addc A,#data
			tmp = GETBIT(CY);
			((uint16_t)(ACC + mcu.code[addr+1] + tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (mcu.code[addr+1] & 0x0F) + tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (mcu.code[addr+1] & 0x7F) + tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (mcu.code[addr+1] & 0x7F) + tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += tmp + mcu.code[addr+1];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0x35:	//addc A,direct
			tmp = GETBIT(CY);
			((uint16_t)(ACC + mcu.data[mcu.code[addr+1]] + tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (mcu.data[mcu.code[addr+1]] & 0x0F) + tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (mcu.data[mcu.code[addr+1]] & 0x7F) + tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (mcu.data[mcu.code[addr+1]] & 0x7F) + tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += tmp + mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0x36:	//addc A,@R0
			tmp = GETBIT(CY);
			((uint16_t)(ACC + mcu.data[R0] + tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (mcu.data[R0] & 0x0F) + tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (mcu.data[R0] & 0x7F) + tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (mcu.data[R0] & 0x7F) + tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += tmp + mcu.data[R0];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x37:	//addc A,@R1
			tmp = GETBIT(CY);
			((uint16_t)(ACC + mcu.data[R1] + tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (mcu.data[R1] & 0x0F) + tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (mcu.data[R1] & 0x7F) + tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (mcu.data[R1] & 0x7F) + tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += tmp + mcu.data[R1];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x38:	//addc A,R0
			tmp = GETBIT(CY);
			((uint16_t)(ACC + R0 + tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R0 & 0x0F) + tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R0 & 0x7F) + tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R0 & 0x7F) + tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += tmp + R0;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x39:	//addc A,R1
			tmp = GETBIT(CY);
			((uint16_t)(ACC + R1 + tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R1 & 0x0F) + tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R1 & 0x7F) + tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R1 & 0x7F) + tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += tmp + R1;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x3A:	//addc A,R2
			tmp = GETBIT(CY);
			((uint16_t)(ACC + R2 + tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R2 & 0x0F) + tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R2 & 0x7F) + tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R2 & 0x7F) + tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += tmp + R2;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x3B:	//addc A,R3
			tmp = GETBIT(CY);
			((uint16_t)(ACC + R3 + tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R3 & 0x0F) + tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R3 & 0x7F) + tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R3 & 0x7F) + tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += tmp + R3;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x3C:	//addc A,R4
			tmp = GETBIT(CY);
			((uint16_t)(ACC + R4 + tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R4 & 0x0F) + tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R4 & 0x7F) + tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R4 & 0x7F) + tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += tmp + R4;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x3D:	//addc A,R5
			tmp = GETBIT(CY);
			((uint16_t)(ACC + R5 + tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R5 & 0x0F) + tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R5 & 0x7F) + tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R5 & 0x7F) + tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += tmp + R5;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x3E:	//addc A,R6
			tmp = GETBIT(CY);
			((uint16_t)(ACC + R6 + tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R6 & 0x0F) + tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R6 & 0x7F) + tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R6 & 0x7F) + tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += tmp + R6;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x3F:	//addc A,R7
			tmp = GETBIT(CY);
			((uint16_t)(ACC + R7 + tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) + (R7 & 0x0F) + tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) + (R7 & 0x7F) + tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) + (R7 & 0x7F) + tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC += tmp + R7;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x40:	//jc rel
			mcu.pc+=2;
			if(GETBIT(CY) == 1)
			{
				mcu.pc += (signed char)mcu.code[addr+1];
			}
			break;
		case 0x41:	//ajmp mcu.pc11
			mcu.pc+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0x42:	//orl direct,A
			mcu.data[mcu.code[addr+1]] |= ACC;
			mcu.pc+=2;
			break;
		case 0x43:	//orl direct,#data
			mcu.data[mcu.code[addr+1]] |= mcu.code[addr+2];
			mcu.pc+=3;
			break;
		case 0x44:	//orl A,#data
			ACC |= mcu.code[addr+1];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0x45:	//orl A,direct
			ACC |= mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0x46:	//orl A,@R0
			ACC |= mcu.data[R0];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x47:	//orl A,@R1
			ACC |= mcu.data[R1];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x48:	//orl A,R0
			ACC |= R0;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x49:	//orl A,R1
			ACC |= R1;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x4A:	//orl A,R2
			ACC |= R2;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x4B:	//orl A,R3
			ACC |= R3;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x4C:	//orl A,R4
			ACC |= R4;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x4D:	//orl A,R5
			ACC |= R5;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x4E:	//orl A,R6
			ACC |= R6;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x4F:	//orl A,R7
			ACC |= R7;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x50:	//jnc rel
			mcu.pc+=2;
			if(GETBIT(CY) == 0)
			{
				mcu.pc += (signed char)mcu.code[addr+1];
			}
			break;
		case 0x51:	//acall mcu.pc11
			mcu.pc+=2;
			mcu.data[SP+1] = mcu.pc & 0xFF;
			mcu.data[SP+2] = mcu.pc >> 8;
			SP+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0x52:	//anl direct,A
			mcu.data[mcu.code[addr+1]] |= ACC;
			mcu.pc+=2;
			break;
		case 0x53:	//anl direct,#data
			mcu.data[mcu.code[addr+1]] |= mcu.code[addr+2];
			mcu.pc+=3;
			break;
		case 0x54:	//anl A,#data
			ACC |= mcu.code[addr+1];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0x55:	//anl A,direct
			ACC |= mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0x56:	//anl A,@R0
			ACC |= mcu.data[R0];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x57:	//anl A,@R1
			ACC |= mcu.data[R1];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x58:	//anl A,R0
			ACC |= R0;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x59:	//anl A,R1
			ACC |= R1;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x5A:	//anl A,R2
			ACC |= R2;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x5B:	//anl A,R3
			ACC |= R3;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x5C:	//anl A,R4
			ACC |= R4;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x5D:	//anl A,R5
			ACC |= R5;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x5E:	//anl A,R6
			ACC |= R6;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x5F:	//anl A,R7
			ACC |= R7;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x60:	//jz rel
			mcu.pc+=2;
			if(ACC == 0)
			{
				mcu.pc += (signed char)mcu.code[addr+1];
			}
			break;
		case 0x61:	//ajmp mcu.pc11
			mcu.pc+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0x62:	//xrl direct,A
			mcu.data[mcu.code[addr+1]] ^= ACC;
			mcu.pc+=2;
			break;
		case 0x63:	//xrl direct,#data
			mcu.data[mcu.code[addr+1]] ^= mcu.code[addr+2];
			mcu.pc+=3;
			break;
		case 0x64:	//xrl A,#data
			ACC ^= mcu.code[addr+1];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0x65:	//xrl A,direct
			ACC ^= mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0x66:	//xrl A,@R0
			ACC ^= mcu.data[R0];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x67:	//xrl A,@R1
			ACC ^= mcu.data[R1];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x68:	//xrl A,R0
			ACC ^= R0;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x69:	//xrl A,R1
			ACC ^= R1;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x6A:	//xrl A,R2
			ACC ^= R2;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x6B:	//xrl A,R3
			ACC ^= R3;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x6C:	//xrl A,R4
			ACC ^= R4;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x6D:	//xrl A,R5
			ACC ^= R5;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x6E:	//xrl A,R6
			ACC ^= R6;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x6F:	//xrl A,R7
			ACC ^= R7;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x70:	//jnz rel
			mcu.pc+=2;
			if(ACC != 0)
			{
				mcu.pc += (signed char)mcu.code[addr+1];
			}
			break;
		case 0x71:	//acall mcu.pc11
			mcu.pc+=2;
			mcu.data[SP+1] = mcu.pc & 0xFF;
			mcu.data[SP+2] = mcu.pc >> 8;
			SP+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0x72:	//orl C,bit
			if(GETBIT(mcu.code[addr+1]) == 1)
				SETBIT(CY);
			mcu.pc+=2;
			break;
		case 0x73:	//jmp @A+DPTR
			mcu.pc = ACC + DPTR;
			break;
		case 0x74:	//mov A,#data
			ACC = mcu.code[addr+1];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0x75:	//mov direct,#data
			mcu.data[mcu.code[addr+1]] = mcu.code[addr+2];
			mcu.pc+=3;
			break;
		case 0x76:	//mov @R0,#data
			mcu.data[R0] = mcu.code[addr+1];
			mcu.pc+=2;
			break;
		case 0x77:	//mov @R1,#data
			mcu.data[R1] = mcu.code[addr+1];
			mcu.pc+=2;
			break;
		case 0x78:	//mov R0,#data
			R0 = mcu.code[addr+1];
			mcu.pc+=2;
			break;
		case 0x79:	//mov R1,#data
			R1 = mcu.code[addr+1];
			mcu.pc+=2;
			break;
		case 0x7A:	//mov R2,#data
			R2 = mcu.code[addr+1];
			mcu.pc+=2;
			break;
		case 0x7B:	//mov R3,#data
			R3 = mcu.code[addr+1];
			mcu.pc+=2;
			break;
		case 0x7C:	//mov R4,#data
			R4 = mcu.code[addr+1];
			mcu.pc+=2;
			break;
		case 0x7D:	//mov R5,#data
			R5 = mcu.code[addr+1];
			mcu.pc+=2;
			break;
		case 0x7E:	//mov R6,#data
			R6 = mcu.code[addr+1];
			mcu.pc+=2;
			break;
		case 0x7F:	//mov R7,#data
			R7 = mcu.code[addr+1];
			mcu.pc+=2;
			break;
		case 0x80:	//sjmp mcu.pc
			mcu.pc += 2 + (signed char)mcu.code[addr+1];
			break;
		case 0x81:	//ajmp mcu.pc11
			mcu.pc+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0x82:	//anl C,bit
			if(GETBIT(mcu.code[addr+1]) == 0)
				CLRBIT(CY);
			mcu.pc+=2;
			break;
		case 0x83:	//movc A,@A+PC
			mcu.pc++;
			ACC = mcu.code[ACC+mcu.pc];
			CHECKPARITY();
			break;
		case 0x84:	//div AB
			CLRBIT(CY);
			CLRBIT(OV);
			tmp = ACC / mcu.data[0xF0];
			mcu.data[0xF0] = ACC % mcu.data[0xF0];
			ACC = tmp;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x85:	//mov direct,direct
			mcu.data[mcu.code[addr+1]] = mcu.data[mcu.code[addr+2]];
			mcu.pc+=3;
			break;
		case 0x86:	//mov direct,@R0
			mcu.data[mcu.code[addr+1]] = mcu.data[R0];
			mcu.pc+=2;
			break;
		case 0x87:	//mov direct,@R1
			mcu.data[mcu.code[addr+1]] = mcu.data[R1];
			mcu.pc+=2;
			break;
		case 0x88:	//mov direct,R0
			mcu.data[mcu.code[addr+1]] = R0;
			mcu.pc+=2;
			break;
		case 0x89:	//mov direct,R1
			mcu.data[mcu.code[addr+1]] = R1;
			mcu.pc+=2;
			break;
		case 0x8A:	//mov direct,R2
			mcu.data[mcu.code[addr+1]] = R2;
			mcu.pc+=2;
			break;
		case 0x8B:	//mov direct,R3
			mcu.data[mcu.code[addr+1]] = R3;
			mcu.pc+=2;
			break;
		case 0x8C:	//mov direct,R4
			mcu.data[mcu.code[addr+1]] = R4;
			mcu.pc+=2;
			break;
		case 0x8D:	//mov direct,R5
			mcu.data[mcu.code[addr+1]] = R5;
			mcu.pc+=2;
			break;
		case 0x8E:	//mov direct,R6
			mcu.data[mcu.code[addr+1]] = R6;
			mcu.pc+=2;
			break;
		case 0x8F:	//mov direct,R7
			mcu.data[mcu.code[addr+1]] = R7;
			mcu.pc+=2;
			break;
		case 0x90:	//mov DPTR,#data
			DPH = mcu.code[addr+1];
			DPL = mcu.code[addr+2];
			mcu.pc+=3;
			break;
		case 0x91:	//acall mcu.pc11
			mcu.pc+=2;
			mcu.data[SP+1] = mcu.pc & 0xFF;
			mcu.data[SP+2] = mcu.pc >> 8;
			SP+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0x92:	//mov bit,C
			if(GETBIT(CY) == 0)
			{
				CLRBIT(mcu.code[addr+1]);
			} else {
				SETBIT(mcu.code[addr+1]);
			}
			mcu.pc+=2;
			break;
		case 0x93:	//movc A,@A+DPTR
			ACC = mcu.code[ACC+DPTR];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x94:	//subb A,#data
			tmp = GETBIT(CY);
			((uint16_t)(ACC - mcu.code[addr+1] - tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) - (mcu.code[addr+1] & 0x0F) - tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) - (mcu.code[addr+1] & 0x7F) - tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) - (mcu.code[addr+1] & 0x7F) - tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC -= tmp + mcu.code[addr+1];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0x95:	//subb A,direct
			tmp = GETBIT(CY);
			((uint16_t)(ACC - mcu.data[mcu.code[addr+1]] - tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) - (mcu.data[mcu.code[addr+1]] & 0x0F) - tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) - (mcu.data[mcu.code[addr+1]] & 0x7F) - tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) - (mcu.data[mcu.code[addr+1]] & 0x7F) - tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC -= tmp + mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0x96:	//subb A,@R0
			tmp = GETBIT(CY);
			((uint16_t)(ACC - mcu.data[R0] - tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) - (mcu.data[R0] & 0x0F) - tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) - (mcu.data[R0] & 0x7F) - tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) - (mcu.data[R0] & 0x7F) - tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC -= tmp + mcu.data[R0];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x97:	//subb A,@R1
			tmp = GETBIT(CY);
			((uint16_t)(ACC - mcu.data[R1] - tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) - (mcu.data[R1] & 0x0F) - tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) - (mcu.data[R1] & 0x7F) - tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) - (mcu.data[R1] & 0x7F) - tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC -= tmp + mcu.data[R1];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x98:	//subb A,R0
			tmp = GETBIT(CY);
			((uint16_t)(ACC - R0 - tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) - (R0 & 0x0F) - tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) - (R0 & 0x7F) - tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) - (R0 & 0x7F) - tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC -= tmp + R0;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x99:	//subb A,R1
			tmp = GETBIT(CY);
			((uint16_t)(ACC - R1 - tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) - (R1 & 0x0F) - tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) - (R1 & 0x7F) - tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) - (R1 & 0x7F) - tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC -= tmp + R1;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x9A:	//subb A,R2
			tmp = GETBIT(CY);
			((uint16_t)(ACC - R2 - tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) - (R2 & 0x0F) - tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) - (R2 & 0x7F) - tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) - (R2 & 0x7F) - tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC -= tmp + R2;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x9B:	//subb A,R3
			tmp = GETBIT(CY);
			((uint16_t)(ACC - R3 - tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) - (R3 & 0x0F) - tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) - (R3 & 0x7F) - tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) - (R3 & 0x7F) - tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC -= tmp + R3;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x9C:	//subb A,R4
			tmp = GETBIT(CY);
			((uint16_t)(ACC - R4 - tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) - (R4 & 0x0F) - tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) - (R4 & 0x7F) - tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) - (R4 & 0x7F) - tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC -= tmp + R4;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x9D:	//subb A,R5
			tmp = GETBIT(CY);
			((uint16_t)(ACC - R5 - tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) - (R5 & 0x0F) - tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) - (R5 & 0x7F) - tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) - (R5 & 0x7F) - tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC -= tmp + R5;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x9E:	//subb A,R6
			tmp = GETBIT(CY);
			((uint16_t)(ACC - R6 - tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) - (R6 & 0x0F) - tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) - (R6 & 0x7F) - tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) - (R6 & 0x7F) - tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC -= tmp + R6;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0x9F:	//subb A,R7
			tmp = GETBIT(CY);
			((uint16_t)(ACC - R7 - tmp) > 0xFF) ? SETBIT(CY) : CLRBIT(CY);
			(((ACC & 0x0F) - (R7 & 0x0F) - tmp) > 0x0F) ? SETBIT(AC) : CLRBIT(AC);
			(((((ACC & 0x7F) - (R7 & 0x7F) - tmp) > 0x7F) && (GETBIT(CY) == 0)) || ((((ACC & 0x7F) - (R7 & 0x7F) - tmp) <= 0x7F) && (GETBIT(CY) == 1))) ? SETBIT(OV) : CLRBIT(OV);
			ACC -= tmp + R7;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xA0:	//orl C,/bit
			if(GETBIT(mcu.code[addr+1]) == 0)
				SETBIT(CY);
			mcu.pc+=2;
			break;
		case 0xA1:	//ajmp mcu.pc11
			mcu.pc+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0xA2:	//mov C,bit
			if(GETBIT(mcu.code[addr+1]) == 0)
			{
				CLRBIT(CY);
			} else {
				SETBIT(CY);
			}
			mcu.pc+=2;
			break;
		case 0xA3:	//inc DPTR;
			if(DPL != 0xFF)
			{
				DPL++;
			} else {
				DPL++;
				DPH++;
			}
			mcu.pc+=3;
			break;
		case 0xA4:	//mul AB
			((uint16_t)(ACC * mcu.data[0xF0]) > 0xFF) ? SETBIT(OV) : CLRBIT(OV);
			CLRBIT(CY);
			tmp16 = ACC * mcu.data[0xF0];
			ACC = tmp16 & 0xFF;
			mcu.data[0xF0] = tmp16 >> 8;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xA5:	//reserved
			// breakpoint opcode
			// this opcode should acts like nop
			mcu.pc++;
			break;
		case 0xA6:	//mov @R0,direct
			mcu.data[R0] = mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			break;
		case 0xA7:	//mov @R1,direct
			mcu.data[R1] = mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			break;
		case 0xA8:	//mov R0,direct
			R0 = mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			break;
		case 0xA9:	//mov R1,direct
			R1 = mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			break;
		case 0xAA:	//mov R2,direct
			R2 = mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			break;
		case 0xAB:	//mov R3,direct
			R3 = mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			break;
		case 0xAC:	//mov R4,direct
			R4 = mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			break;
		case 0xAD:	//mov R5,direct
			R5 = mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			break;
		case 0xAE:	//mov R6,direct
			R6 = mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			break;
		case 0xAF:	//mov R7,direct
			R7 = mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			break;
		case 0xB0:	//anl C,/bit
			if(GETBIT(mcu.code[addr+1]) == 1)
				CLRBIT(CY);
			mcu.pc+=2;
			break;
		case 0xB1:	//acall mcu.pc11
			mcu.pc+=2;
			mcu.data[SP+1] = mcu.pc & 0xFF;
			mcu.data[SP+2] = mcu.pc >> 8;
			SP+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0xB2:	//cpl bit
			if(GETBIT(mcu.code[addr+1]) == 0)
			{
				SETBIT(mcu.code[addr+1]);
			} else {
				CLRBIT(mcu.code[addr+1]);
			}
			mcu.pc+=2;
			break;
		case 0xB3:	//cpl C
			if(GETBIT(CY) == 0)
			{
				SETBIT(CY);
			} else {
				CLRBIT(CY);
			}
			mcu.pc++;
			break;
		case 0xB4:	//cjne A,#data,mcu.pc
			mcu.pc+=3;
			if(ACC != mcu.code[addr+1])
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xB5:	//cjne A,direct,mcu.pc
			mcu.pc+=3;
			if(ACC != mcu.data[mcu.code[addr+1]])
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xB6:	//cjne @R0,#data,mcu.pc
			mcu.pc+=3;
			if(mcu.data[R0] != mcu.code[addr+1])
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xB7:	//cjne @R1,#data,mcu.pc
			mcu.pc+=3;
			if(mcu.data[R1] != mcu.code[addr+1])
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xB8:	//cjne R0,#data,mcu.pc
			mcu.pc+=3;
			if(R0 != mcu.code[addr+1])
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xB9:	//cjne R1,#data,mcu.pc
			mcu.pc+=3;
			if(R1 != mcu.code[addr+1])
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xBA:	//cjne R2,#data,mcu.pc
			mcu.pc+=3;
			if(R2 != mcu.code[addr+1])
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xBB:	//cjne R3,#data,mcu.pc
			mcu.pc+=3;
			if(R3 != mcu.code[addr+1])
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xBC:	//cjne R4,#data,mcu.pc
			mcu.pc+=3;
			if(R4 != mcu.code[addr+1])
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xBD:	//cjne R5,#data,mcu.pc
			mcu.pc+=3;
			if(R5 != mcu.code[addr+1])
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xBE:	//cjne R6,#data,mcu.pc
			mcu.pc+=3;
			if(R6 != mcu.code[addr+1])
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xBF:	//cjne R7,#data,mcu.pc
			mcu.pc+=3;
			if(R7 != mcu.code[addr+1])
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xC0:	//push direct
			SP++;
			mcu.data[SP] = mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			break;
		case 0xC1:	//ajmp mcu.pc11
			mcu.pc+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0xC2:	//clr bit
			CLRBIT(mcu.code[addr+1]);
			mcu.pc+=2;
			break;
		case 0xC3:	//clr C
			CLRBIT(CY);
			mcu.pc++;
			break;
		case 0xC4:	//swap A
			ACC = (ACC << 4) + (ACC >> 4);
			mcu.pc++;
			break;
		case 0xC5:	//xch A,direct
			tmp = mcu.data[mcu.code[addr+1]];
			mcu.data[mcu.code[addr+1]] = ACC;
			ACC = tmp;
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0xC6:	//xch A,@R0
			tmp = mcu.data[R0];
			mcu.data[R0] = ACC;
			ACC = tmp;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xC7:	//xch A,@R1
			tmp = mcu.data[R1];
			mcu.data[R1] = ACC;
			ACC = tmp;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xC8:	//xch A,R0
			tmp = R0;
			R0 = ACC;
			ACC = tmp;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xC9:	//xch A,R1
			tmp = R1;
			R1 = ACC;
			ACC = tmp;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xCA:	//xch A,R2
			tmp = R2;
			R2 = ACC;
			ACC = tmp;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xCB:	//xch A,R3
			tmp = R3;
			R3 = ACC;
			ACC = tmp;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xCC:	//xch A,R4
			tmp = R4;
			R4 = ACC;
			ACC = tmp;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xCD:	//xch A,R5
			tmp = R5;
			R5 = ACC;
			ACC = tmp;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xCE:	//xch A,R6
			tmp = R6;
			R6 = ACC;
			ACC = tmp;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xCF:	//xch A,R7
			tmp = R7;
			R7 = ACC;
			ACC = tmp;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xD0:	//pop direct
			mcu.data[mcu.code[addr+1]] = mcu.data[SP];
			SP--;
			mcu.pc+=2;
			break;
		case 0xD1:	//acall mcu.pc11
			mcu.pc+=2;
			mcu.data[SP+1] = mcu.pc & 0xFF;
			mcu.data[SP+2] = mcu.pc >> 8;
			SP+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0xD2:	//setb bit
			SETBIT(mcu.code[addr+1]);
			mcu.pc+=2;
			break;
		case 0xD3:	//setb C
			SETBIT(CY);
			mcu.pc++;
			break;
		case 0xD4:	//da A
			if(((ACC & 0x0F) > 9) || (GETBIT(AC) == 1))
			{
				if((uint16_t)(ACC + 0x06) > 0xFF)
					SETBIT(CY);
				ACC += 0x06;
			}
			if((((ACC & 0xF0) >> 4) > 9) || (GETBIT(CY) == 1))
			{
				if((uint16_t)(ACC + 0x60) > 0xFF)
					SETBIT(CY);
				ACC += 0x60;
			}
			(ACC > 0x99) ? SETBIT(CY) : CLRBIT(CY);
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xD5:	//djnz direct,rel
			mcu.pc += 3;
			mcu.data[mcu.code[addr+1]]--;
			if(mcu.data[mcu.code[addr+1]] != 0)
				mcu.pc += (signed char)mcu.code[addr+2];
			break;
		case 0xD6:	//xchd A,@R0
			tmp = mcu.data[R0];
			mcu.data[R0] = (mcu.data[R0] & 0xF0) + (ACC & 0x0F);
			ACC = (ACC & 0xF0) + (tmp & 0x0F);
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xD7:	//xchd A,@R1
			tmp = mcu.data[R1];
			mcu.data[R1] = (mcu.data[R1] & 0xF0) + (ACC & 0x0F);
			ACC = (ACC & 0xF0) + (tmp & 0x0F);
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xD8:	//djnz R0,rel
			mcu.pc += 2;
			R0--;
			if(R0 != 0)
				mcu.pc += (signed char)mcu.code[addr+1];
			break;
		case 0xD9:	//djnz R1,rel
			mcu.pc+=2;
			R1--;
			if(R1 != 0)
				mcu.pc += (signed char)mcu.code[addr+1];
			break;
		case 0xDA:	//djnz R2,rel
			mcu.pc+=2;
			R2--;
			if(R2 != 0)
				mcu.pc += (signed char)mcu.code[addr+1];
			break;
		case 0xDB:	//djnz R3,rel
			mcu.pc+=2;
			R3--;
			if(R3 != 0)
				mcu.pc += (signed char)mcu.code[addr+1];
			break;
		case 0xDC:	//djnz R4,rel
			mcu.pc+=2;
			R4--;
			if(R4 != 0)
				mcu.pc += (signed char)mcu.code[addr+1];
			break;
		case 0xDD:	//djnz R5,rel
			mcu.pc+=2;
			R5--;
			if(R5 != 0)
				mcu.pc += (signed char)mcu.code[addr+1];
			break;
		case 0xDE:	//djnz R6,rel
			mcu.pc+=2;
			R6--;
			if(R6 != 0)
				mcu.pc += (signed char)mcu.code[addr+1];
			break;
		case 0xDF:	//djnz R7,rel
			mcu.pc+=2;
			R7--;
			if(R7 != 0)
				mcu.pc += (signed char)mcu.code[addr+1];
			break;
		case 0xE0:	//movx A,@DPTR
			ACC = mcu.xdata[DPTR];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xE1:	//ajmp mcu.pc11
			mcu.pc+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0xE2:	//movx A,@R0
			ACC = mcu.xdata[(P2 << 8) + R0];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xE3:	//movx A,@R1
			ACC = mcu.xdata[(P2 << 8) + R1];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xE4:	//clr A
			ACC = 0;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xE5:	//mov A,direct
			ACC = mcu.data[mcu.code[addr+1]];
			mcu.pc+=2;
			CHECKPARITY();
			break;
		case 0xE6:	//mov A,@R0
			ACC = mcu.data[R0];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xE7:	//mov A,@R1
			ACC = mcu.data[R1];
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xE8:	//mov A,R0
			ACC = R0;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xE9:	//mov A,R1
			ACC = R1;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xEA:	//mov A,R2
			ACC = R2;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xEB:	//mov A,R3
			ACC = R3;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xEC:	//mov A,R4
			ACC = R4;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xED:	//mov A,R5
			ACC = R5;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xEE:	//mov A,R6
			ACC = R6;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xEF:	//mov A,R7
			ACC = R7;
			mcu.pc++;
			CHECKPARITY();
			break;
		case 0xF0:	//movx @DPTR,A
			mcu.xdata[DPTR] = ACC;
			mcu.pc++;
			break;
		case 0xF1:	//acall mcu.pc11
			mcu.pc+=2;
			mcu.data[SP+1] = mcu.pc & 0xFF;
			mcu.data[SP+2] = mcu.pc >> 8;
			SP+=2;
			mcu.pc = (mcu.pc & 0xF800) + ((mcu.code[addr] & 0xE0) << 3) + mcu.code[addr+1];
			break;
		case 0xF2:	//movx @R0,A
			mcu.xdata[(P2 << 8) + R0] = ACC;
			mcu.pc++;
			break;
		case 0xF3:	//movx @R1,A
			mcu.xdata[(P2 << 8) + R1] = ACC;
			mcu.pc++;
			break;
		case 0xF4:	//cpl A
			ACC = ~ACC;
			mcu.pc++;
			break;
		case 0xF5:	//mov direct,A
			mcu.data[mcu.code[addr+1]] = ACC;
			mcu.pc+=2;
			break;
		case 0xF6:	//mov @R0,A
			mcu.data[R0] = ACC;
			mcu.pc++;
			break;
		case 0xF7:	//mov @R1,A
			mcu.data[R1] = ACC;
			mcu.pc++;
			break;
		case 0xF8:	//mov R0,A
			R0 = ACC;
			mcu.pc++;
			break;
		case 0xF9:	//mov R1,A
			R1 = ACC;
			mcu.pc++;
			break;
		case 0xFA:	//mov R2,A
			R2 = ACC;
			mcu.pc++;
			break;
		case 0xFB:	//mov R3,A
			R3 = ACC;
			mcu.pc++;
			break;
		case 0xFC:	//mov R4,A
			R4 = ACC;
			mcu.pc++;
			break;
		case 0xFD:	//mov R5,A
			R5 = ACC;
			mcu.pc++;
			break;
		case 0xFE:	//mov R6,A
			R6 = ACC;
			mcu.pc++;
			break;
		case 0xFF:	//mov R7,A
			R7 = ACC;
			mcu.pc++;
			break;

		default:
			mcu.pc++;
	}
	
	ncycles = 0;

	for ( i = 0; i < NINSTRUCTIONS ; i++ )
	{
		if ( mcu.code[addr] == inst[i].opcode )
		{
			ncycles = inst[i].ncycles;
			break;
		}
	}

	if(((TMOD & 0xC0) == 0) && (GETBIT(TR0) == 1))
	{
		switch(TMOD & 0x30)
		{
			case 1:
				if((uint16_t)(TL0 + ncycles) > 0xFF)
				{
					(TH0 == 0xFF) ? SETBIT(TF0) : CLRBIT(TF0);
					TH0++;
				}
				TL0 += ncycles;
				break;
			case 2:
				if((uint16_t)(TL0 + ncycles) > 0xFF)
				{
					SETBIT(TF0);
					TL0 += ncycles + TH0;
				} else {
					CLRBIT(TF0);
					TL0 += ncycles;
				}
				break;
		}
	}

	if(((TMOD & 0xC0) == 0) && (GETBIT(TR1) == 1))
	{
		switch((TMOD & 0x30) >> 4)
		{
			case 1:
				if((uint16_t)(TL1 + ncycles) > 0xFF)
				{
					(TH1 == 0xFF) ? SETBIT(TF1) : CLRBIT(TF1);
					TH1++;
				}
				TL1 += ncycles;
				break;
			case 2:
				if((uint16_t)(TL1 + ncycles) > 0xFF)
				{
					SETBIT(TF1);
					TL1 += ncycles + TH1;
				} else {
					CLRBIT(TF1);
					TL1 += ncycles;
				}
				break;
		}
	}
	
        return &mcu;
}


void
 close ( void )
{
}

plugin_sym_t functions = {
	.init = init ,
	.disasm = disasm ,
	/* .regmmap = regs_mmap , */
	.simul = simul ,
	.get_memcode = get_memory_code ,
	.get_memram = get_internal_ram ,
	.get_memxram = get_external_ram ,
	.get_reg = get_register ,
	.get_pc = get_pc ,
	.close = close
};

